﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;
using FRW.Common.Extensions;
using Money.Plugins;

namespace Money.Interface
{
    // TODO fix the issue that the displayed category changes when the date range is changed using DateRange control
    // TODO update so that only categories containing data are displayed

    public partial class CategoryBreakdownGraph : GraphControl, IGraph
    {
        public CategoryBreakdownGraph()
            : base()
        {
            InitializeComponent();

            InitialiseControls();

            Name = "Category Breakdown";
        }

        /// <summary>
        /// 
        /// </summary>
        private void InitialiseControls()
        {
        }

        public override void UpdateGraph(object sender, DateChangedEventArgs e)
        {
            // Prepare a list of categories that have transactions within them
            // TODO should we change this so that only debits are included?
            var categoryList = from t in _dataInterface.Transactions
                               where t.Amount <= 0
                               group t by t.ParentId;

            List<Category> categories = new List<Category>();

            foreach (var category in categoryList)
            {
                int categoryId = category.First<Transaction>().ParentId;
                string categoryName = _dataInterface.Categories.Find(iter => iter.Id == category.First<Transaction>().ParentId).Name;
                categories.Add(new Category() { Id = categoryId, Name = categoryName + " (" + category.Count<Transaction>() + ")" });
            }

            categories = categories.OrderBy(category => category.Name).ToList();             

            // Update the selection box to allow the selection of valid categories
            _subCategorySelection.DataSource = categories;
            _subCategorySelection.DisplayMember = "Name";
            _subCategorySelection.ValueMember = "Id";

            _category = _dataInterface.Categories.Find(category => category.Id == categories[0].Id).Name;

            _startDate = e.StartDate;
            _endDate = e.EndDate;

            DrawGraph(_startDate, _endDate);
        }

        private void DrawGraph(DateTime startDate, DateTime endDate)
        {
            int categoryId = _dataInterface.Categories.Find(category => category.Name.Equals(_category)).Id;
            List<DateTime> range = startDate.MonthsBetween(endDate).ToList();

            // We ignore any transaction that has a positive amount (credits e.g. salary)
            // We ignore all transfer transactions as no spend takes place with these
            // We ignore all transactions marked as ignore
            // TODO we should make it configurable somewhere what should be shown
            var filteredTransactions = from transaction
                        in _dataInterface.Transactions.Where(Transactions.InDateRange(startDate, endDate).Compile())
                                       where transaction.Amount <= 0
                                             && transaction.Type != Transaction.TransactionType.Transfer
                                             && transaction.Type != Transaction.TransactionType.Ignore
                                             && transaction.ParentId == categoryId
                                       orderby transaction.Date ascending
                                       select transaction;

            var categoryGroups = from t
            in filteredTransactions
                                 orderby t.Category ascending
                                 group t by t.Category into gp
                                 select new
                                 {
                                     Category = gp.Key,
                                     Group = gp
                                 };

            // HACK
            try
            {
                if (_graph.Series != null)
                {
                    _graph.Series.Clear();
                }
            }
            catch
            {
            }
            _graph.Tag = "SubCategories";

            foreach (var categoryGroup in categoryGroups)
            {
                var categorySpend =
                                from dr in range
                                join transaction in categoryGroup.Group
                                on dr.StartOfMonth() equals transaction.Date.StartOfMonth()
                                into joinedGroups
                                from joinedGroup in joinedGroups.DefaultIfEmpty(new Transaction() { Date = dr.StartOfMonth() })
                                group joinedGroup by joinedGroup.Date.StartOfMonth() into jgp
                                select new { Month = jgp.Key, Amount = jgp.Sum(tt => -tt.Amount) };

                //_graph.Series.Clear();
                Series series = new Series();

                series.ChartArea = "default";
                series.ChartType = SeriesChartType.StackedColumn;
                series.Legend = "default";
                series.Name = categoryGroup.Category;
                series.SmartLabelStyle.IsOverlappedHidden = false;
                series.XValueType = ChartValueType.Date;
                _graph.Series.Add(series);

                //_graph.Series[series.Name]["DrawingStyle"] = "Cylinder";
                _graph.Series[series.Name].Points.DataBind(categorySpend.ToList(), "Month", "Amount", "");
                //            _graph.Series[series.Name].ShadowOffset = 2;

              //  _graph.Tag = "SubCategories";
            }
        }

        private void cbSubCategory_SelectedIndexChanged(object sender, EventArgs e)
        {
            //_category = cbSubCategory.Text;
            Category selectedValue = _subCategorySelection.SelectedItem as Category;

            if (selectedValue != null)
            {
                _startDate = (from t in _dataInterface.Transactions select t.Date).Min();
                _endDate = (from t in _dataInterface.Transactions select t.Date).Max();
                _category = _dataInterface.Categories.Find(category => category.Id == selectedValue.Id).Name;
                DrawGraph(_startDate, _endDate);

                OnFiltered();
            }
        }
    }
}
